package pl.edu.mimuw.irs.core.model.analysis;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;

import pl.edu.mimuw.irs.core.model.analysis.workflow.AnalysisWorkflow;
import pl.edu.mimuw.irs.rcp.util.Logger;
import pl.edu.mimuw.irs.rcp.util.MessageCode;


public class Report {

	// *** Properties
	
	public static final String RUNS_CUSTOMIZED = "RUNS_CUSTOMIZED";
	
	// *** Attributes

	private transient PropertyChangeSupport listeners;
	private List<History> runs;
	private List<History> customRuns;
	private int count;
	private AnalysisWorkflow workflow;
	private Date start;
	private Date end;
	public PropertyChangeSupport getListeners() {
		if (listeners == null) listeners = new PropertyChangeSupport(this);
		return listeners;
	}
	public List<History> getRuns() {
		if (runs == null) runs = new ArrayList<History>(count);
		return runs;
	}
	public void addRun(History history) {
		getRuns().add(history);
	}
	public AnalysisWorkflow getWorkflow() {
		return workflow;
	}
	public Date getStart() {
		return start;
	}
	public Date getEnd() {
		return end;
	}
	public List<History> getCustomRuns() {
		if (customRuns == null) customRuns = new LinkedList<History>(getRuns());
		return customRuns;
	}
	public void setCustomRuns(List<History> customRuns) {
		List<History> oldRuns = this.customRuns;
		this.customRuns = customRuns;
		getListeners().firePropertyChange(RUNS_CUSTOMIZED, oldRuns, customRuns);
	}
	
	
	// *** Constructors
	
	public Report(AnalysisWorkflow workflow) {
		this.workflow = workflow;
	}

	// *** Methods
	
	public void generate(IProgressMonitor monitor, int runs) {
		this.count = runs;
		start = new Date();
		for (int i = 0; i < runs; i++) {
			try {
				History history = workflow.run();
				if (history != null) addRun(history);
				workflow.reset();
				monitor.worked(1);
			} catch (Exception e) {
				e.printStackTrace();
				Logger.handle(MessageCode.ANALYSIS_CREATE_PROBLEM, e);
				break;
			}
		}
		end = new Date();
	}

	public List<History> getFastest() {
		Collections.sort(getCustomRuns(), new FastestComparator());
		return getRuns();
	}

	public List<History> getCheapest() {
		Collections.sort(getCustomRuns(), new CheapestComparator());
		return getRuns();
	}
	
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		getListeners().addPropertyChangeListener(listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener) {
		getListeners().removePropertyChangeListener(listener);
	}
	
	public class FastestComparator implements Comparator<History> {

		@Override
		public int compare(History arg0, History arg1) {
			return arg0.getTimestamp().getValue() - arg1.getTimestamp().getValue();
		}
	}

	public class CheapestComparator implements Comparator<History> {

		@Override
		public int compare(History arg0, History arg1) {
			return arg0.getTotalUsageCost() - arg1.getTotalUsageCost();
		}
	}
}
